"""
配置信息管理

提供应用程序配置管理功能，包括：
- JSON配置文件读取
- 环境变量配置
- 配置合并和优先级
- 数据库配置管理
"""

import json
import os.path
from pathlib import Path
from typing import Any, Dict, Literal
from uuid import uuid4

from pydantic import Field, BaseModel
from pydantic.fields import FieldInfo
from pydantic_settings import (
    PydanticBaseSettingsSource,
    BaseSettings,
    SettingsConfigDict,
)

# 配置目录和当前环境
current_dir = os.path.dirname(__file__)
config_dir = os.path.join(current_dir, "config_files")
rags_env = os.environ.get("APP_ENV") or "test"


class JsonConfigSettingSource(PydanticBaseSettingsSource):
    """
    JSON配置源
    
    从JSON文件中读取配置信息，支持基础配置和环境特定配置
    """
    
    def __call__(self) -> dict[str, Any]:
        """
        获取配置数据
        
        Returns:
            dict[str, Any]: 配置数据字典
        """
        d: Dict[str, Any] = {}
        base_config = self.__read_config("base.json")
        env_config = {}
        if rags_env:
            env_config = self.__read_config(f"{rags_env}.json")

        for field_name, field in self.settings_cls.model_fields.items():
            field_value = self.get_field_value(
                field, field_name, base_config, env_config
            )
            if field_value is not None:
                d[field_name] = field_value
        return d

    def __read_config(self, file_name: str) -> dict:
        """
        读取配置文件
        
        Args:
            file_name: 配置文件名
            
        Returns:
            dict: 配置数据
        """
        encoding = self.config.get("env_file_encoding")
        config_path = Path(f"{config_dir}/{file_name}")
        value = {}
        if config_path.exists():
            config_value = config_path.read_text(encoding)
            if config_value:
                value = json.loads(config_value)
        return value

    def get_field_value(
        self,
        field: FieldInfo,
        field_name: str,
        base_value: dict | None = None,
        env_value: dict | None = None,
    ) -> Any:
        """
        获取字段值
        
        Args:
            field: 字段信息
            field_name: 字段名
            base_value: 基础配置值
            env_value: 环境配置值
            
        Returns:
            Any: 字段值
        """
        base_value = base_value or {}
        env_value = env_value or {}
        is_model = False
        try:
            is_model = issubclass(field.annotation, BaseModel)
        except:
            pass
        if is_model:
            field_value = {}
            for sub_field_name, sub_field in field.annotation.model_fields.items():
                sub_field_value = self.get_field_value(
                    sub_field,
                    sub_field_name,
                    base_value.get(field_name),
                    env_value.get(field_name),
                )
                if sub_field_value is not None:
                    field_value.update({sub_field_name: sub_field_value})
        else:
            field_value = env_value.get(field_name)
            if field_value is None:
                field_value = base_value.get(field_name)
        return field_value


class _DbConfig(BaseModel):
    """
    数据库基础配置
    """
    host: str = Field(description="host")
    port: int = Field(description="端口")
    user: str = Field(description="用户")
    password: str = Field(description="密码")
    db: str = Field(description="数据库名")


class _MysqlConfig(_DbConfig):
    """
    MySQL数据库配置
    
    包含连接池配置参数
    """
    pool_size: int = Field(5, description="数据库连接池大小")
    max_overflow: int = Field(20, description="数据库连接池最大可以超出多少")
    pool_recycle: int = Field(30, description="多久回收连接,单位s")


class _Settings(BaseSettings):
    """
    应用程序设置
    
    管理所有配置信息，支持从多个源加载配置
    """
    model_config = SettingsConfigDict(
        env_file_encoding="utf-8", env_nested_delimiter="__"
    )
    mysql: _MysqlConfig = Field(description="mysql配置信息")

    def settings_customise_sources(
        self,
        settings_cls: type[BaseSettings],
        init_settings: PydanticBaseSettingsSource,
        env_settings: PydanticBaseSettingsSource,
        dotenv_settings: PydanticBaseSettingsSource,
        file_secret_settings: PydanticBaseSettingsSource,
    ) -> tuple[PydanticBaseSettingsSource, ...]:
        """
        自定义配置源
        
        设置配置源的优先级顺序
        
        Args:
            settings_cls: 设置类
            init_settings: 初始化设置
            env_settings: 环境变量设置
            dotenv_settings: 环境文件设置
            file_secret_settings: 文件秘密设置
            
        Returns:
            tuple[PydanticBaseSettingsSource, ...]: 配置源元组
        """
        return (
            init_settings,
            env_settings,
            JsonConfigSettingSource(settings_cls),
            file_secret_settings,
        )


_settings = _Settings()

mysql = _settings.mysql
